package name.weily.liba.views.menu

import android.content.Context
import android.graphics.PixelFormat
import android.os.Build
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.WindowManager
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import com.google.android.material.floatingactionbutton.FloatingActionButton
import name.weily.liba.tools.dp2px
import name.weily.liba.tools.runIfApiAfter

class FloatingMenu(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0)
    : LinearLayout(context, attributeSet, defStyleAttr), View.OnClickListener
    , LifecycleObserver {

    companion object {
        private const val Tag = "FloatingMenu"
        const val TYPE_ACTIVITY = 0
        const val TYPE_SYSTEM = 1
    }

    private var floatingType = TYPE_ACTIVITY
                    set(value) {
                        field = value
                        wlp.type = convertFloatingType(value)
                    }

    private val wlp: WindowManager.LayoutParams by lazy {  WindowManager.LayoutParams().apply {
        width = WindowManager.LayoutParams.WRAP_CONTENT
        height = WindowManager.LayoutParams.WRAP_CONTENT
        gravity = Gravity.BOTTOM or Gravity.END

        type = convertFloatingType(floatingType)

        format = PixelFormat.TRANSLUCENT
        //FLAG_NOT_FOCUSABLE: outside menu can click;
        //FLAG_NOT_TOUCH_MODAL: outside menu input can type
        flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
//                    or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
//                    or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
    } }

    var onMenuItemClickListener: ((View, Int) -> Unit)? = null

    private var lifecycleOwner : LifecycleOwner? = null
                    set(value) {
                        field?.lifecycle?.removeObserver(this)
                        field = value
                        field?.lifecycle?.addObserver(this)
                    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private fun destroy() {
        hide()
    }

    override fun onClick(v: View?) {
        onMenuItemClickListener?.let {
            children.forEachIndexed { index, view ->
                if (view == v) {
                    hide()
                    it.invoke(v, index)
                }
            }
        }
    }

    init {
        val padding = context.dp2px(32)
        setPadding(padding, padding, padding, padding)
        orientation = LinearLayout.VERTICAL
    }


    fun <T : View> addMenuItem(item: T, position: Int = -1) : FloatingMenu {
        item.setOnClickListener(this)
        if (position >= 0) {
            addView(item, position)
        } else {
            addView(item, 0)
        }
        return this
    }

    fun setMenuItemVisible(index: Int, visible: Boolean) {
        getChildAt(index)?.let {
            it.isEnabled = visible
        }
    }

    fun hideMenuItems() {
        children.forEachIndexed { index, view ->
            if (index < childCount - 1) {
                view.isEnabled = false
            }
        }
    }

    private fun convertFloatingType(showType: Int) : Int {
        return when (showType) {
            TYPE_ACTIVITY -> {
                WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
            }
            else -> {
                runIfApiAfter(Build.VERSION_CODES.O,
                    beforeTargetApi = {
                        WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
                    }, afterTargetApi = {
                        WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
                    })
            }
        }
    }

    fun show(activity: AppCompatActivity, showType: Int = TYPE_ACTIVITY) {
        if (isShown) {
            return
        }
        lifecycleOwner = activity
        (context.getSystemService(Context.WINDOW_SERVICE) as? WindowManager)
            ?.let {
                if (showType != floatingType) {
                    floatingType = showType
                }
                it.addView(this, wlp)
            }
    }

    fun hide() {
        (context?.getSystemService(Context.WINDOW_SERVICE) as? WindowManager)?.let {
            if (this.isShown) {
                it.removeViewImmediate(this)
            }
        }
        lifecycleOwner = null
    }
}

class FloatingMenuItem(context: Context, attributeSet: AttributeSet? = null, defStyleAttr: Int = 0)
    : FloatingActionButton(context, attributeSet, defStyleAttr) {
}

